/**
* @file XtTradeFramework.cpp
* @brief 迅投增强交易框架 Framework 源文件
* @details 具体功能实现
* @author zhangtao
* @version 1.0.0
* @date 2019-04-02
*/

#if _MSC_VER > 1600
#pragma execution_character_set("utf-8")
#endif

#include <fstream> 
#include <iostream>
#include <stdarg.h>
#include <map>
#include <thread>
#include <time.h>
#include "XtTradeFramework.h"
#include "XtDataType.h"
#include "XtTranscoding.h"
#include "NetManager.h"
#include "WrapperSpi.h"
#include <functional>
#include <windows.h>
#include <tchar.h>
#include "util.h"
using namespace std;
CAccountDetail stockAccount;    ///< 股票账号信息
CAccountDetail creditAccount;   ///< 两融账号信息
map<string, CStkSubjectDetail> m_key2CStkSubjectDetail;     ///< 标的信息
map<string, CStkCompactDetail> m_key2CStkCompactDetail;     ///< 负债合约

std::function<void(const char*, const char*, const char*, XtError)>* rtn_call_back = nullptr;//func_name    msg   key  error  外传函数
HINSTANCE	g_dll;
string      g_tag;
/**************************************************************************
                            内部函数声明开始
**************************************************************************/
/**
* @brief 测试股票委托
* @param[in] account 账号明细，从onReqAccountDetail或onRtnAccountDetail接口的返回
* @param[in] nRequestId 客户自己维护的请求顺序ID
* @note 其中函数内部包含执行委托的部分信息，客户可以重定义或者重载该函数
*/
void testStockOrder(const CAccountDetail& account, int nRequestId);

/**
* @brief 测试期货下单
* @param[in] account 账号明细，从onReqAccountDetail或onRtnAccountDetail接口的返回
* @param[in] nRequestId 客户自己维护的请求顺序ID
* @note 其中函数内部包含执行委托的部分信息，客户可以重定义或者重载该函数
*/
void testFutureOrder(const CAccountDetail& account, int nRequestId);

/**
* @brief 测试信用下单
* @param[in] account 账号明细，从onReqAccountDetail或onRtnAccountDetail接口的返回
* @param[in] nRequestId 客户自己维护的请求顺序ID
* @note 其中函数内部包含执行委托的部分信息，客户可以重定义或者重载该函数
*/
void testCreditOrder(const CAccountDetail& account, int nRequestId);

/**
* @brief 测试个股期权下单
* @param[in] account 账号明细，从onReqAccountDetail或onRtnAccountDetail接口的返回
* @param[in] nRequestId 客户自己维护的请求顺序ID
* @note 其中函数内部包含执行委托的部分信息，客户可以重定义或者重载该函数
*/
void testOptionOrder(const CAccountDetail& account, int nRequestId);

/**
* @brief 测试沪港通下单
* @param[in] account 账号明细，从onReqAccountDetail或onRtnAccountDetail接口的返回
* @param[in] nRequestId 客户自己维护的请求顺序ID
* @note 其中函数内部包含执行委托的部分信息，客户可以重定义或者重载该函数
*/
void testHgtOrder(const CAccountDetail& account, int nRequestId);

/**
* @brief 测试深港通下单
* @param[in] account 账号明细，从onReqAccountDetail或onRtnAccountDetail接口的返回
* @param[in] nRequestId 客户自己维护的请求顺序ID
* @note 其中函数内部包含执行委托的部分信息，客户可以重定义或者重载该函数
*/
void testSgtOrder(const CAccountDetail& account, int nRequestId);

/**
* @brief 测试策略下单
* @param[in] accountKey 通过account->getKey()获取
* @note 其中函数内部包含执行策略的部分信息，客户可以重定义或者重载该函数
*/
void testPlaceOrder(const char* accountKey);

/**
* @brief 测试循环定时下单，这里为客户提供一个定时报单思路
* @param[in] account 账号明细，从onReqAccountDetail或onRtnAccountDetail接口的返回
* @param[in] nRequestId 客户自己维护的请求顺序ID
* @note 其中函数内部包含执行策略的部分信息，客户可以重定义或者重载该函数
*/
void testLoopOrder(const CAccountDetail& account, int nRequestId);

/**
* @brief 加载配置信息
* @param[out] m_mapConfigInfo 配置文件内容map结构
*/
void ConfigFileRead(map<string, string>& m_mapConfigInfo);

/**
* @brief 测试配置参数下单，这里为客户提供一个配置报单思路
* @param[in] account 账号明细，从onReqAccountDetail或onRtnAccountDetail接口的返回
* @param[in] nRequestId 客户自己维护的请求顺序ID
* @note 客户可以重定义或者重载该函数
*/
void testConfigOrder(const CAccountDetail& account, int nRequestId);

/**************************************************************************
                            内部函数声明结束
**************************************************************************/





void setNetCb(HINSTANCE handle);

/**
* @brief 整个dll的函数入口
* 当此dll被加载时会调用此函数，此时查询函数绑定已经完成。
*/
void onInit(const char* moduleTag)
{

    FileAdapter::GetInstance().flush_to_file("Frame.log", "framework version 3434\n");
    g_tag = moduleTag;
    //------------------------------dll         test



   // LPCWSTR str = _T("D:\\DOWNLOAD_FILE\\TradeSdk\\Framework1.0.3\\demo\\x64\\Release\\mydll.dll");
    LPCWSTR str = _T("mydll.dll");

    // D:\DOWNLOAD_FILE\TradeSdk\Framework1.0.3\demo\_runtime\x64.Release\XtTradeFramework.dll
    g_dll = LoadLibrary(str);
    //HINSTANCE	dll = LoadLibraryEx(str, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
    if (!g_dll) {
        FileAdapter::GetInstance().flush_to_file("Frame.log", "dll load fail !\n");
        return;
    }

     setNetCb(g_dll);
    

    //----------------------------------------------------

    // moduleTag 需要保存下来，所有查询函数需要使用此tag进行请求，以方便主程序区分不同dll。
     m_moduleTag = moduleTag;
    // 获取所有账号的资金明细，nRequestId 为 1(此id需要保证不重且自增)，moduleTag 使用保存下来的tag。
    // 回调会调用 onReqAccountDetail。
     //typedef void (*InitNet)(const char* moduleTag, CAccountDetail acct, CAccountDetail credit);


     //InitNet fun = (InitNet)GetProcAddress(g_dll, "InitNet");
    // fun(g_tag.c_str(), stockAccount, creditAccount);
       reqAllAccountDetail(1, m_moduleTag);

    /*订阅号，退订接口参数*/
    //int requestId = 1;
    //CPriceData data = reqPriceData("SH", "600000", ++requestId, m_moduleTag);
    //long long subscribeNo = subscribeQuote("SH", "600000", 0, ++requestId, m_moduleTag);
    //unsubscribeQuote(subscribeNo, ++requestId, m_moduleTag);
    //CAccountDetail data;
    //strcpy(data.m_strAccountID, "2037879");
    //int nRes = 1;
    //testOrder(data, nRes);
    //CAccountDetail data;
    //strcpy(data.m_strAccountID, "2037879");
    //int nRes = 1;
    //testOrder(data, nRes);
   // typedef NetManager<int, OrderPolicy> NETCLASS;
   // NetManager<int, OrderPolicy> manager;
   // thread worker(&NETCLASS::init, manager);
   // function<void(const char *,const char *,const char *, XtError )>  *obj =  new //func_name    msg   key  error

}



void onNotify(const XtError & error)
{
    if (!error.isSuccess())
    {

    }
}

// 查询账号资金回调 账号资金明细 查询id 是否是此次查询最后一条数据 错误信息
void onReqAccountDetail(const CAccountDetail& data, const char* accountKey, int nRequestId, bool isLast, const XtError& error)
{
    // 判断是否有错误返回
    if (error.isSuccess())
    {


        /*测试报单*/
        if (XTFW_AT_STOCK == data.m_nBrokerType)
        {
            // testStockOrder(data, ++nRequestId);
            stockAccount = data;
            memcpy(stockAccount.m_strAccountKey, accountKey, strlen(accountKey));
            string msg = "[data key]" + string(data.m_strAccountKey) + " " +
                         "[account key]" + string(accountKey);
            FileAdapter::GetInstance().flush_to_file("Frame.log", "BrokerType is Stock !\n");
            FileAdapter::GetInstance().flush_to_file("Frame.log", msg + "\n");
        }
        else {
        
        
        
            stockAccount = data;
            memcpy(stockAccount.m_strAccountKey, accountKey, strlen(accountKey));
            string msg = "[data key]" + string(data.m_strAccountKey) + " " +
                "[account key]" + string(accountKey);
            FileAdapter::GetInstance().flush_to_file("Frame.log", "BrokerType not Stock !\n");
            FileAdapter::GetInstance().flush_to_file("Frame.log", msg + "\n");
        
        }

        typedef void (*InitNet)(const char* moduleTag, CAccountDetail acct, CAccountDetail credit);


        InitNet fun = (InitNet)GetProcAddress(g_dll, "InitNet");

        if (!fun) {

            FileAdapter::GetInstance().flush_to_file("Frame.log", "func load fail\n");
            return;
        }
        FileAdapter::GetInstance().flush_to_file("Frame.log", "NetManager Call !\n");
        fun(g_tag.c_str(), stockAccount, creditAccount);



    }
}

// order 以及 cancelAction统一回调函数 
void onOrder(const CTradeAction& data, const char* accountKey, int nRequestId, const XtError& error)
{
    if (error.isSuccess())
    {
        typedef void (*ONORDER)(const CTradeAction& data, const char* accountKey, int nRequestId, const XtError& error);
        // 此时可以通过data.m_nTaskId 和data.m_nGroupID 进行撤单
        ONORDER fun = (ONORDER)GetProcAddress(g_dll, "rtn_cancel_order");
        fun(data, accountKey, nRequestId, error);
        
    }
    else
    {

    }
}

// 委托明细主推
void onRtnOrderDetail(const COrderDetail& data, const char* accountKey, int nRequestId, const XtError& error)
{
    if (error.isSuccess())
    {

        typedef void (*ORDER_DETAIL)(const COrderDetail& data, const char* accountKey, int nRequestId, const XtError& error);
        // 此时可以通过data.m_nTaskId 和data.m_nGroupID 进行撤单
        ORDER_DETAIL fun = (ORDER_DETAIL)GetProcAddress(g_dll, "rtn_order");
        fun(data, accountKey, nRequestId, error);

        // 如果是已报委托，这里尝试撤单
        if (data.m_eOrderStatus == XTFW_ENTRUST_STATUS_REPORTED)
        {
            // 如果下单动作编号不为-1， 则说明是本系统下单，可以通过撤掉委托动作撤单
            if (data.m_nTaskId != -1 && data.m_nGroupID != -1)
            {
                
            }
            // 如果下单动作编号等于0， 则说明是外部下单，需要通过orderSysID进行委托撤单
            else
            {
                //cancelOrder(data.getKey(), data.m_strOrderSysID, ++nRequestId, m_moduleTag);
            }
        }
    }
    else
    {
    }
}


// 查询账号持仓结果 返回 单条持仓数据 查询id 是否是此次查询最后一条数据 错误信息order
void onReqPositionDetail(const CPositionDetail& data, const char* accountKey, int nRequestId, bool isLast, const XtError& error)
{
    if (error.isSuccess())
    {
    }
    else
    {
    }
}

// 两融查询账号负债合约 返回 单条负债 查询id 是否是此次查询最后一条数据 错误信息
void onReqStkCompactDetail(const CStkCompactDetail& data, const char* accountKey, int nRequestId, bool isLast, const XtError& error)
{
    if (error.isSuccess())
    {
        m_key2CStkCompactDetail[data.getKey()] = data;
    }
    else
    {
    }
}

// 两融查询账号标的 返回 单条证券 查询id 是否是此次查询最后一条数据 错误信息
void onReqStkSubjectDetail(const CStkSubjectDetail& data, const char* accountKey, int nRequestId, bool isLast, const XtError& error)
{
    if (error.isSuccess())
    {
        m_key2CStkSubjectDetail[data.getKey()] = data;
    }
    else
    {
    }
}

// 查询委托结果 返回 单条委托数据 查询id 是否是此次查询最后一条数据 错误信息
void onReqOrderDetail(const COrderDetail& data, const char* accountKey, int nRequestId, bool isLast, const XtError& error)
{
    if (error.isSuccess())
    {
    }
    else
    {
    }
}

// 查询成交结果 返回 单条成交数据 查询id 是否是此次查询最后一条数据 错误信息
void onReqDealDetail(const CDealDetail& data, const char* accountKey, int nRequestId, bool isLast, const XtError& error)
{
    if (error.isSuccess())
    {
    }
    else
    {
    }
}

// 成交数据主推
void onRtnDealDetail(const CDealDetail& data, const char* accountKey, int nRequestId, const XtError& error)
{
    if (error.isSuccess())
    {
        typedef void (*ORDER_TRADE_DETAIL)(const CDealDetail& data, const char* accountKey, int nRequestId, const XtError& error);
        // 此时可以通过data.m_nTaskId 和data.m_nGroupID 进行撤单
        ORDER_TRADE_DETAIL fun = (ORDER_TRADE_DETAIL)GetProcAddress(g_dll, "rtn_trade");
        fun(data, accountKey, nRequestId, error);
    }
    else
    {

    }
}

// 账号资金明细主推
void onRtnAccountDetail(const CAccountDetail& data, const char* accountKey, int nRequestId, const XtError& error)
{
    
    if (error.isSuccess())
    {
        printf("sucess\n");
    }
    else
    {
        printf("fail\n");

    }
}


// 账号资金明细主推
void onRtnPriceData(const CPriceData& data)
{
    
}

// 账号登录状态主推
void onRtnLoginStatus(const EXtFWLoginStatus status, const char* accountKey, const XtError& error)
{
    if (error.isSuccess())
    {
    }
    else
    {
    }
}

void onSetStockWhiteList(const CStockWhiteList& data, const char* accountKey, bool isLast, const XtError& error)
{
    if (error.isSuccess())
    {
    }
    else
    {
    }
}

// 查询委托结果 返回 单条委托数据 查询id 是否是此次查询最后一条数据 错误信息
void onReqStockWhiteList(const CStockWhiteList& data, const char* accountKey, int nRequestId, bool isLast, const XtError& error)
{
    if (error.isSuccess())
    {
    }
    else
    {
    }
}

// 主推策略绩效数据
void sendTradeStatData(const CTradeStatData& data, const char* accountKey)
{
}

// 查询融券可融数量结果 返回 单条数据 查询id 是否是此次查询最后一条数据 错误信息
void onReqCreditSloEnableAmt(const CCreditSloEnableAmt& data, const char* accountKey, int nRequestId, bool isLast, const XtError& error)
{
    if (error.isSuccess())
    {
    }
    else
    {
    }
}

// 查询账号两融综合资金回调 账号两融综合资金明细 查询id 是否是此次查询最后一条数据 错误信息
void onReqCreditDetail(const CCreditDetail& data, const char* accountKey, int nRequestId, bool isLast, const XtError& error)
{
    if (error.isSuccess())
    {
    }
    else
    {
    }
}

// 两融查询账号为了结负债合约 返回 单条负债 查询id 是否是此次查询最后一条数据 错误信息
void onReqStkUnClosedCompactDetail(const CStkUnClosedCompactDetail& data, const char* accountKey, int nRequestId, bool isLast, const XtError& error)
{
    if (error.isSuccess())
    {
    }
    else
    {
    }
}

// 两融查询账号已了结负债合约 返回 单条负债 查询id 是否是此次查询最后一条数据 错误信息
void onReqStkClosedCompactDetail(const CStkClosedCompactDetail& data, const char* accountKey, int nRequestId, bool isLast, const XtError& error)
{
    if (error.isSuccess())
    {
    }
    else
    {
    }
}

// 两融查询账号融资融券标的 返回 单条证券 查询id 是否是此次查询最后一条数据 错误信息
void onReqCreditSubjectDetail(const CCreditSubjectDetail& data, const char* accountKey, int nRequestId, bool isLast, const XtError& error)
{
    if (error.isSuccess())
    {
    }
    else
    {
    }
}

// 两融查询账号担保品标的 返回 单条证券 查询id 是否是此次查询最后一条数据 错误信息
void onReqCreditAssureDetail(const CCreditAssureDetail& data, const char* accountKey, int nRequestId, bool isLast, const XtError& error)
{
    if (error.isSuccess())
    {
    }
    else
    {
    }
}

/*
* 测试下单函数
*/
void testStockOrder(const CAccountDetail& account, int nRequestId)
{
    cout << "testStockOrder call" << endl;
    cout << account.m_dAvailable << endl;
    FileAdapter::GetInstance().flush_to_file("Frame.log", "testStockOrder call \n");
    /*
    // 填充下单参数 以 19.1元的价格 买入 上海证券交易所 600000 股票 500股。
    COrdinaryOrder orderInfo;
    orderInfo.m_dPrice = 19.1;
    orderInfo.m_nOrderNum = 1000;
    strcpy(orderInfo.m_strExchangeID, XTFW_MARKET_SHANGHAI);
    strcpy(orderInfo.m_strInstrumentID, "600004");
    strcpy(orderInfo.m_strAccountKey, account.getKey());
    orderInfo.m_eOperationType = XTFW_OPT_BUY;
    orderInfo.m_ePriceType = XTFW_PRTP_LATEST; //使用最新价,价格没用
    strcpy(orderInfo.m_strRemark, "测试股票买入");

    // 下单函数 返回下单动作操作 onOrder 或 等待订阅的委托主推 onRtnOrderDetail。
    order(orderInfo, nRequestId, m_moduleTag);
    */
}
void testFutureOrder(const CAccountDetail& account, int nRequestId)
{
    // 填充下单参数 以 19.1元的价格 开仓 上期所 a1901。
    COrdinaryOrder orderInfo;
    orderInfo.m_dPrice = 19.1;
    orderInfo.m_nOrderNum = 2;
    strcpy(orderInfo.m_strExchangeID, XTFW_MARKET_DALIANG_FUTURE);
    strcpy(orderInfo.m_strInstrumentID, "a1905");
    strcpy(orderInfo.m_strAccountKey, account.getKey());
    orderInfo.m_eOperationType = XTFW_OPT_OPEN_LONG;
    orderInfo.m_ePriceType = XTFW_PRTP_LATEST; //使用最新价,价格没用
    strcpy(orderInfo.m_strRemark, "测试期货开仓");

    // 下单函数 返回下单动作操作 onOrder 或 等待订阅的委托主推 onRtnOrderDetail。
    order(orderInfo, nRequestId, m_moduleTag);
}

void testPlaceOrder(const char* accountKey)
{
    XtError error;
    //添加策略
    nID = addStrategy(m_moduleTag, error);
    if (error.isSuccess())
    {
        //startStrategy(1, m_moduleTag);
        CStrategyDetail strategy;
        strategy.m_nID = nID;
        strcpy(strategy.m_strAccountKey, accountKey);
        strcpy(strategy.m_strFilePath, "../config/test.txt");
        strcpy(strategy.m_strName, "策略1");
        strategy.m_eTradeType = XTFW_STRATEGY_TRADE_TYPE_SPEC;
        //更新策略信息
        error = updateStrategy(nID, strategy, m_moduleTag);
        if (error.isSuccess())
        {
            //启动文件单
            error = startStrategy(nID, m_moduleTag);
            if (error.isSuccess())
            {
                //文件单启动成功
            }
            else
            {
                //文件单启动失败
            }
        }
        else
        {

        }
    }

}
void testCreditOrder(const CAccountDetail& account, int nRequestId)
{
    // 填充下单参数 以 19.1元的价格 融资买入 上海证券交易所 600000 股票 500股（需要查标的）。
    if (account.m_nBrokerType == 3)
    {
        COrdinaryOrder orderInfo;
        orderInfo.m_dPrice = 12.4;
        orderInfo.m_nOrderNum = 500;
        strcpy(orderInfo.m_strExchangeID, XTFW_MARKET_SHANGHAI);
        strcpy(orderInfo.m_strInstrumentID, "600000");
        strcpy(orderInfo.m_strAccountKey, account.getKey());
        orderInfo.m_eOperationType = XTFW_OPT_FIN_BUY;
        orderInfo.m_ePriceType = XTFW_PRTP_LATEST; //使用最新价,价格没用
        strcpy(orderInfo.m_strRemark, "测试融资买入");

        // 下单函数 返回下单动作操作 onOrder 或 等待订阅的委托主推 onRtnOrderDetail。
        order(orderInfo, nRequestId, m_moduleTag);
    }
}

void testLoopOrder(const CAccountDetail& account, int nRequestId)
{
    // 填充下单参数 以 19.1元的价格 融资买入 上海证券交易所 600000 股票 500股（需要查标的）。

    if (account.m_nBrokerType == 2)
    {
        COrdinaryOrder orderInfo;
        orderInfo.m_dPrice = 12.24;
        orderInfo.m_nOrderNum = 100;
        strcpy(orderInfo.m_strExchangeID, XTFW_MARKET_SHENZHEN);
        strcpy(orderInfo.m_strInstrumentID, "000001");
        strcpy(orderInfo.m_strAccountKey, account.getKey());
        orderInfo.m_ePriceType = XTFW_PRTP_LATEST; //使用最新价,价格没用

        orderInfo.m_eOperationType = XTFW_OPT_BUY;
        strcpy(orderInfo.m_strRemark, "test loop order 100 times");
        for (int i = 0; i < 100; i++)
        {
            float secs = 5;
            clock_t delay;
            delay = secs * CLOCKS_PER_SEC;
            clock_t start = clock();
            while (clock() - start < delay);
            // 下单函数 返回下单动作操作 onOrder 或 等待订阅的委托主推 onRtnOrderDetail。
            order(orderInfo, nRequestId, m_moduleTag);
        }
    }
}

void testOptionOrder(const CAccountDetail& account, int nRequestId)
{
    // 填充下单参数 以 19.1元的价格 融资买入 上海证券交易所 600000 股票 500股（需要查标的）。
    if (account.m_nBrokerType == 6)
    {
        COrdinaryOrder orderInfo;
        orderInfo.m_dPrice = 0.3429;
        orderInfo.m_nOrderNum = 1;
        strcpy(orderInfo.m_strExchangeID, XTFW_MARKET_SHANGHAI_STOCK_OPTION);
        strcpy(orderInfo.m_strInstrumentID, "10001417");
        strcpy(orderInfo.m_strAccountKey, account.getKey());
        orderInfo.m_ePriceType = XTFW_PRTP_LATEST; //使用最新价,价格没用

        orderInfo.m_eOperationType = XTFW_OPT_OPTION_BUY_OPEN;
        strcpy(orderInfo.m_strRemark, "测试期权买入开仓");
        // 下单函数 返回下单动作操作 onOrder 或 等待订阅的委托主推 onRtnOrderDetail。
        order(orderInfo, nRequestId, m_moduleTag);

        orderInfo.m_eOperationType = XTFW_OPT_OPTION_SELL_CLOSE;
        strcpy(orderInfo.m_strRemark, "测试期权卖出平仓");
        // 下单函数 返回下单动作操作 onOrder 或 等待订阅的委托主推 onRtnOrderDetail。
        order(orderInfo, nRequestId, m_moduleTag);

        orderInfo.m_eOperationType = XTFW_OPT_OPTION_SELL_OPEN;
        strcpy(orderInfo.m_strRemark, "测试期权卖出开仓");
        // 下单函数 返回下单动作操作 onOrder 或 等待订阅的委托主推 onRtnOrderDetail。
        order(orderInfo, nRequestId, m_moduleTag);

        orderInfo.m_eOperationType = XTFW_OPT_OPTION_BUY_CLOSE;
        strcpy(orderInfo.m_strRemark, "测试期权买入平仓");
        // 下单函数 返回下单动作操作 onOrder 或 等待订阅的委托主推 onRtnOrderDetail。
        order(orderInfo, nRequestId, m_moduleTag);

        orderInfo.m_eOperationType = XTFW_OPT_OPTION_COVERED_OPEN;
        strcpy(orderInfo.m_strRemark, "测试期权备兑开仓");
        // 下单函数 返回下单动作操作 onOrder 或 等待订阅的委托主推 onRtnOrderDetail。
        order(orderInfo, nRequestId, m_moduleTag);

        orderInfo.m_eOperationType = XTFW_OPT_OPTION_COVERED_CLOSE;
        strcpy(orderInfo.m_strRemark, "测试期权备兑平仓");
        // 下单函数 返回下单动作操作 onOrder 或 等待订阅的委托主推 onRtnOrderDetail。
        order(orderInfo, nRequestId, m_moduleTag);

        orderInfo.m_eOperationType = XTFW_OPT_OPTION_CALL_EXERCISE;
        strcpy(orderInfo.m_strRemark, "测试期权认购行权");
        // 下单函数 返回下单动作操作 onOrder 或 等待订阅的委托主推 onRtnOrderDetail。
        order(orderInfo, nRequestId, m_moduleTag);

        orderInfo.m_eOperationType = XTFW_OPT_OPTION_PUT_EXERCISE;
        strcpy(orderInfo.m_strRemark, "测试期权认沽行权");
        // 下单函数 返回下单动作操作 onOrder 或 等待订阅的委托主推 onRtnOrderDetail。
        order(orderInfo, nRequestId, m_moduleTag);


        strcpy(orderInfo.m_strExchangeID, XTFW_MARKET_SHANGHAI);
        strcpy(orderInfo.m_strInstrumentID, "600000");
        orderInfo.m_eOperationType = XTFW_OPT_OPTION_SECU_LOCK;
        strcpy(orderInfo.m_strRemark, "测试期权证券锁定");
        // 下单函数 返回下单动作操作 onOrder 或 等待订阅的委托主推 onRtnOrderDetail。
        order(orderInfo, nRequestId, m_moduleTag);

        orderInfo.m_eOperationType = XTFW_OPT_OPTION_SECU_UNLOCK;
        strcpy(orderInfo.m_strRemark, "测试期权证券解锁");
        // 下单函数 返回下单动作操作 onOrder 或 等待订阅的委托主推 onRtnOrderDetail。     
        order(orderInfo, nRequestId, m_moduleTag);
    }
}
void testHgtOrder(const CAccountDetail& account, int nRequestId)
{
    // 填充下单参数 以 19.1元的价格 融资买入 上海证券交易所 600000 股票 500股（需要查标的）。
    if (account.m_nBrokerType == 7)
    {
        COrdinaryOrder orderInfo;
        orderInfo.m_dPrice = 82.95;
        orderInfo.m_nOrderNum = 500;
        strcpy(orderInfo.m_strExchangeID, XTFW_MARKET_SHANGHAI_HONGKONG_STOCK);
        strcpy(orderInfo.m_strInstrumentID, "00001");
        strcpy(orderInfo.m_strAccountKey, account.getKey());
        orderInfo.m_ePriceType = XTFW_PRTP_LATEST; //使用最新价,价格没用
        orderInfo.m_eOperationType = XTFW_OPT_BUY;
        strcpy(orderInfo.m_strRemark, "测试沪港通买入");
        // 下单函数 返回下单动作操作 onOrder 或 等待订阅的委托主推 onRtnOrderDetail。
        order(orderInfo, nRequestId, m_moduleTag);

        orderInfo.m_eOperationType = XTFW_OPT_SELL;
        strcpy(orderInfo.m_strRemark, "测试沪港通卖出");
        // 下单函数 返回下单动作操作 onOrder 或 等待订阅的委托主推 onRtnOrderDetail。
        order(orderInfo, nRequestId, m_moduleTag);
    }
}

void testSgtOrder(const CAccountDetail& account, int nRequestId)
{
    // 填充下单参数 以 19.1元的价格 融资买入 上海证券交易所 600000 股票 500股（需要查标的）。
    if (account.m_nBrokerType == 11)
    {
        COrdinaryOrder orderInfo;
        orderInfo.m_dPrice = 82.95;
        orderInfo.m_nOrderNum = 500;
        strcpy(orderInfo.m_strExchangeID, XTFW_MARKET_SHENZHEN_HONGKONG_STOCK);
        strcpy(orderInfo.m_strInstrumentID, "00001");
        strcpy(orderInfo.m_strAccountKey, account.getKey());
        orderInfo.m_ePriceType = XTFW_PRTP_LATEST; //使用最新价,价格没用

        orderInfo.m_eOperationType = XTFW_OPT_BUY;
        strcpy(orderInfo.m_strRemark, "测试深港通买入");
        // 下单函数 返回下单动作操作 onOrder 或 等待订阅的委托主推 onRtnOrderDetail。
        order(orderInfo, nRequestId, m_moduleTag);
        orderInfo.m_eOperationType = XTFW_OPT_SELL;
        strcpy(orderInfo.m_strRemark, "测试深港通卖出");
        // 下单函数 返回下单动作操作 onOrder 或 等待订阅的委托主推 onRtnOrderDetail。
        order(orderInfo, nRequestId, m_moduleTag);
    }
}

void testConfigOrder(const CAccountDetail& account, int nRequestId)
{
    // 填充下单参数 以 19.1元的价格 融资买入 上海证券交易所 600000 股票 500股（需要查标的）。
    if (account.m_nBrokerType == 2)
    {
        map<string, string> m_mapConfigInfo;
        ConfigFileRead(m_mapConfigInfo);
        COrdinaryOrder orderInfo;
        if (m_mapConfigInfo.find("price") != m_mapConfigInfo.end())
        {
            orderInfo.m_dPrice = atof(m_mapConfigInfo["price"].c_str());
        }
        if (m_mapConfigInfo.find("orderNum") != m_mapConfigInfo.end())
        {
            orderInfo.m_nOrderNum = atoi(m_mapConfigInfo["orderNum"].c_str());
        }
        if (m_mapConfigInfo.find("exchangeID") != m_mapConfigInfo.end())
        {
            string tmp = m_mapConfigInfo["exchangeID"];
            strcpy(orderInfo.m_strExchangeID, tmp.c_str());
            orderInfo.m_strExchangeID[tmp.length()] = '\0';
        }
        if (m_mapConfigInfo.find("instrumentID") != m_mapConfigInfo.end())
        {
            string tmp = m_mapConfigInfo["instrumentID"];
            strcpy(orderInfo.m_strInstrumentID, tmp.c_str());
            orderInfo.m_strInstrumentID[tmp.length()] = '\0';
        }
        strcpy(orderInfo.m_strAccountKey, account.getKey());
        if (m_mapConfigInfo.find("priceType") != m_mapConfigInfo.end())
        {
            orderInfo.m_ePriceType = (EXtFWPriceType)atoi(m_mapConfigInfo["priceType"].c_str());
        }
        if (m_mapConfigInfo.find("operationType") != m_mapConfigInfo.end())
        {
            orderInfo.m_eOperationType = (EXtFWOperationType)atoi(m_mapConfigInfo["operationType"].c_str());
        }
        if (m_mapConfigInfo.find("remark") != m_mapConfigInfo.end())
        {
            string tmp = m_mapConfigInfo["remark"];
            strcpy(orderInfo.m_strRemark, tmp.c_str());
            orderInfo.m_strRemark[tmp.length()] = '\0';
        }
        order(orderInfo, nRequestId, m_moduleTag);
    }
}

void ConfigFileRead(map<string, string>& m_mapConfigInfo)
{
    std::ifstream configFile;
    /*请保证该路径下包含该文件*/
    string path = "../orderConf/setting.conf";
    configFile.open(path.c_str());
    string str_line;
    if (configFile.is_open())
    {
        while (!configFile.eof())
        {
            getline(configFile, str_line);
            if (str_line.find('#') == 0) //过滤掉注释信息，即如果首个字符为#就过滤掉这一行
            {
                continue;
            }
            size_t pos = str_line.find('=');
            string str_key = str_line.substr(0, pos);
            string str_value = str_line.substr(pos + 1);
            m_mapConfigInfo.insert(pair<string, string>(str_key, str_value));
        }
    }
}







void setNetCb(HINSTANCE handle) {
     
    typedef  void (*OrderT)( void(*reqAllAccountDeatilCallBack) (const CAccountDetail& detail, int request   ));
    typedef  void (*ORDER) ( void(*order) (const COrdinaryOrder& orderInfo, int nRequestId, const char* moduleTag ));
    typedef  void(*CANCELACTION)(void(*cancel_order)(const char* accountKey, const long long nTaskId, const long long nGroupId, int nRequestId, const char* moduleTag));



    OrderT fun_order_t = (OrderT)GetProcAddress(handle, "SetOrderTest");
    ORDER  fun_order = (ORDER)GetProcAddress(handle, "SetOrder");
    CANCELACTION  fun_cancel_order = (CANCELACTION)GetProcAddress(handle, "SetCancelOrder");



    fun_order_t(testStockOrder);
    fun_order (order);
    fun_cancel_order(cancelAction);

}
